﻿namespace DomainServices.Tools.Pdb.SymStore
{
    using System;
    using System.Diagnostics.SymbolStore;
    using System.Runtime.InteropServices;
    using System.Runtime.InteropServices.ComTypes;
    using System.Text;

    internal class SymReader : ISymbolReader2, ISymbolReader, ISymbolReaderSymbolSearchInfo, ISymbolEncUpdate, IDisposable
    {
        private ISymUnmanagedReader m_reader;

        internal SymReader(ISymUnmanagedReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }
            this.m_reader = reader;
        }

        public void Dispose()
        {
            GC.SuppressFinalize(this);
            ISymUnmanagedDispose reader = this.m_reader as ISymUnmanagedDispose;
            if (reader != null)
            {
                reader.Destroy();
            }
            this.m_reader = null;
        }

        public ISymbolDocument GetDocument(string url, Guid language, Guid languageVendor, Guid documentType)
        {
            ISymUnmanagedDocument retVal = null;
            this.m_reader.GetDocument(url, language, languageVendor, documentType, out retVal);
            if (retVal == null)
            {
                return null;
            }
            return new SymbolDocument(retVal);
        }

        public ISymbolDocument[] GetDocuments()
        {
            int pcDocs = 0;
            this.m_reader.GetDocuments(0, out pcDocs, null);
            ISymUnmanagedDocument[] pDocs = new ISymUnmanagedDocument[pcDocs];
            this.m_reader.GetDocuments(pcDocs, out pcDocs, pDocs);
            ISymbolDocument[] documentArray2 = new SymbolDocument[pcDocs];
            for (uint i = 0; i < pcDocs; i++)
            {
                documentArray2[i] = new SymbolDocument(pDocs[i]);
            }
            return documentArray2;
        }

        public int GetDocumentVersion(ISymbolDocument document, out bool isCurrent)
        {
            int version = 0;
            this.m_reader.GetDocumentVersion(((SymbolDocument) document).InternalDocument, out version, out isCurrent);
            return version;
        }

        public ISymbolVariable[] GetGlobalVariables()
        {
            int pcVars = 0;
            this.m_reader.GetGlobalVariables(0, out pcVars, null);
            ISymUnmanagedVariable[] vars = new ISymUnmanagedVariable[pcVars];
            this.m_reader.GetGlobalVariables(pcVars, out pcVars, vars);
            SymVariable[] variableArray2 = new SymVariable[pcVars];
            for (uint i = 0; i < pcVars; i++)
            {
                variableArray2[i] = new SymVariable(vars[i]);
            }
            return variableArray2;
        }

        public int GetLocalVariableCount(SymbolToken mdMethodToken)
        {
            int pcLocals = 0;
            ((ISymUnmanagedEncUpdate) this.m_reader).GetLocalVariableCount(mdMethodToken, out pcLocals);
            return pcLocals;
        }

        public ISymbolVariable[] GetLocalVariables(SymbolToken mdMethodToken)
        {
            int pceltFetched = 0;
            ((ISymUnmanagedEncUpdate) this.m_reader).GetLocalVariables(mdMethodToken, 0, null, out pceltFetched);
            ISymUnmanagedVariable[] rgLocals = new ISymUnmanagedVariable[pceltFetched];
            ((ISymUnmanagedEncUpdate) this.m_reader).GetLocalVariables(mdMethodToken, pceltFetched, rgLocals, out pceltFetched);
            ISymbolVariable[] variableArray2 = new ISymbolVariable[pceltFetched];
            for (uint i = 0; i < pceltFetched; i++)
            {
                variableArray2[i] = new SymVariable(rgLocals[i]);
            }
            return variableArray2;
        }

        public ISymbolMethod GetMethod(SymbolToken method)
        {
            ISymUnmanagedMethod retVal = null;
            int errorCode = this.m_reader.GetMethod(method, out retVal);
            if (errorCode == -2147467259)
            {
                return null;
            }
            Marshal.ThrowExceptionForHR(errorCode);
            return new SymMethod(retVal);
        }

        public ISymbolMethod GetMethod(SymbolToken method, int version)
        {
            ISymUnmanagedMethod retVal = null;
            int errorCode = this.m_reader.GetMethodByVersion(method, version, out retVal);
            if (errorCode == -2147467259)
            {
                return null;
            }
            Marshal.ThrowExceptionForHR(errorCode);
            return new SymMethod(retVal);
        }

        public ISymbolMethod GetMethodFromDocumentPosition(ISymbolDocument document, int line, int column)
        {
            ISymUnmanagedMethod retVal = null;
            this.m_reader.GetMethodFromDocumentPosition(((SymbolDocument) document).InternalDocument, line, column, out retVal);
            return new SymMethod(retVal);
        }

        public ISymbolMethod[] GetMethodsFromDocumentPosition(ISymbolDocument document, int line, int column)
        {
            int pcMethod = 0;
            this.m_reader.GetMethodsFromDocumentPosition(((SymbolDocument) document).InternalDocument, line, column, 0, out pcMethod, null);
            ISymUnmanagedMethod[] pRetVal = new ISymUnmanagedMethod[pcMethod];
            this.m_reader.GetMethodsFromDocumentPosition(((SymbolDocument) document).InternalDocument, line, column, pcMethod, out pcMethod, pRetVal);
            ISymbolMethod[] methodArray2 = new ISymbolMethod[pcMethod];
            for (uint i = 0; i < pcMethod; i++)
            {
                methodArray2[i] = new SymMethod(pRetVal[i]);
            }
            return methodArray2;
        }

        public int GetMethodVersion(ISymbolMethod method)
        {
            int version = 0;
            this.m_reader.GetMethodVersion(((SymMethod) method).InternalMethod, out version);
            return version;
        }

        public ISymbolNamespace[] GetNamespaces()
        {
            int pcNameSpaces = 0;
            this.m_reader.GetNamespaces(0, out pcNameSpaces, null);
            ISymUnmanagedNamespace[] namespaces = new ISymUnmanagedNamespace[pcNameSpaces];
            this.m_reader.GetNamespaces(pcNameSpaces, out pcNameSpaces, namespaces);
            ISymbolNamespace[] namespaceArray2 = new SymNamespace[pcNameSpaces];
            for (uint i = 0; i < pcNameSpaces; i++)
            {
                namespaceArray2[i] = new SymNamespace(namespaces[i]);
            }
            return namespaceArray2;
        }

        public byte[] GetSymAttribute(SymbolToken parent, string name)
        {
            int lengthBuffer = 0;
            this.m_reader.GetSymAttribute(parent, name, 0, out lengthBuffer, null);
            if (lengthBuffer == 0)
            {
                return null;
            }
            byte[] buffer = new byte[lengthBuffer];
            this.m_reader.GetSymAttribute(parent, name, lengthBuffer, out lengthBuffer, buffer);
            return buffer;
        }

        public ISymbolSearchInfo[] GetSymbolSearchInfo()
        {
            int pcSearchInfo = 0;
            ((ISymUnmanagedReaderSymbolSearchInfo) this.m_reader).GetSymbolSearchInfo(0, out pcSearchInfo, null);
            ISymUnmanagedSymbolSearchInfo[] searchInfo = new ISymUnmanagedSymbolSearchInfo[pcSearchInfo];
            ((ISymUnmanagedReaderSymbolSearchInfo) this.m_reader).GetSymbolSearchInfo(pcSearchInfo, out pcSearchInfo, searchInfo);
            ISymbolSearchInfo[] infoArray2 = new ISymbolSearchInfo[pcSearchInfo];
            for (uint i = 0; i < pcSearchInfo; i++)
            {
                infoArray2[i] = new SymSymbolSearchInfo(searchInfo[i]);
            }
            return infoArray2;
        }

        public int GetSymbolSearchInfoCount()
        {
            int pcSearchInfo = 0;
            ((ISymUnmanagedReaderSymbolSearchInfo) this.m_reader).GetSymbolSearchInfoCount(out pcSearchInfo);
            return pcSearchInfo;
        }

        public string GetSymbolStoreFileName()
        {
            int capacity = 0;
            capacity = 300;
            StringBuilder szName = new StringBuilder(capacity);
            this.m_reader.GetSymbolStoreFileName(capacity, out capacity, szName);
            return szName.ToString();
        }

        public ISymbolVariable[] GetVariables(SymbolToken parent)
        {
            int pcVars = 0;
            this.m_reader.GetVariables(parent, 0, out pcVars, null);
            ISymUnmanagedVariable[] vars = new ISymUnmanagedVariable[pcVars];
            this.m_reader.GetVariables(parent, pcVars, out pcVars, vars);
            SymVariable[] variableArray2 = new SymVariable[pcVars];
            for (uint i = 0; i < pcVars; i++)
            {
                variableArray2[i] = new SymVariable(vars[i]);
            }
            return variableArray2;
        }

        public void Initialize(object importer, string filename, string searchPath, IStream stream)
        {
            IntPtr zero = IntPtr.Zero;
            try
            {
                zero = Marshal.GetIUnknownForObject(importer);
                this.m_reader.Initialize(zero, filename, searchPath, stream);
            }
            finally
            {
                if (zero != IntPtr.Zero)
                {
                    Marshal.Release(zero);
                }
            }
        }

        public void ReplaceSymbolStore(string fileName, IStream stream)
        {
            this.m_reader.ReplaceSymbolStore(fileName, stream);
        }

        public void UpdateSymbolStore(IStream stream, SymbolLineDelta[] iSymbolLineDeltas)
        {
            ((ISymUnmanagedEncUpdate) this.m_reader).UpdateSymbolStore2(stream, iSymbolLineDeltas, iSymbolLineDeltas.Length);
        }

        public void UpdateSymbolStore(string fileName, IStream stream)
        {
            this.m_reader.UpdateSymbolStore(fileName, stream);
        }

        public SymbolToken UserEntryPoint
        {
            get
            {
                SymbolToken token;
                int userEntryPoint = this.m_reader.GetUserEntryPoint(out token);
                if (userEntryPoint == -2147467259)
                {
                    return new SymbolToken(0);
                }
                Marshal.ThrowExceptionForHR(userEntryPoint);
                return token;
            }
        }
    }
}

